﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Management;
using System.Text;

namespace SmartMathLibrary.Management.Monitoring
{
    /// <summary>
    /// Occurs when the message limit of the monitor get exceed.
    /// </summary>
    public delegate void VirtualMemoryLimitExceedanceEventHandler(double memoryUsage);

    /// <summary>
    /// This class provides methods to monitor the virtual system memory. All values
    /// have to be declared in the dimension MegaByte.
    /// </summary>
    [Serializable]
    public class VirtualMemoryMonitor : AbstractMemoryMonitor
    {
        /// <summary>
        /// Occurs when the message limit get exceed.
        /// </summary>
        public event VirtualMemoryLimitExceedanceEventHandler VirtualMemoryUsageEvent;

        /// <summary>
        /// Initializes a new instance of the <see cref="VirtualMemoryMonitor"/> class.
        /// </summary>
        /// <param name="messageLimit">The message limit. If the message limit get exceed the monitor
        /// automatically throws a LimitExceedanceEvent.</param>
        /// <param name="samplingRate">The sampling rate.</param>
        public VirtualMemoryMonitor(double messageLimit, double samplingRate)
            : base(messageLimit, samplingRate)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="VirtualMemoryMonitor"/> class.
        /// </summary>
        /// <param name="messageLimit">The message limit. If the message limit get exceed the monitor 
        /// automatically throws a LimitExceedanceEvent.</param>
        /// <param name="samplingRate">The sampling rate.</param>
        /// <param name="startMonitoring">if set to <c>true</c> the monitor will start automatically
        /// otherwise, it must be started by method Start().</param>
        public VirtualMemoryMonitor(double messageLimit, double samplingRate, bool startMonitoring)
            : base(messageLimit, samplingRate, startMonitoring)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="VirtualMemoryMonitor"/> class.
        /// </summary>
        /// <param name="messageLimit">The message limit. If the message limit get exceed the monitor 
        /// automatically throws a LimitExceedanceEvent.</param>
        /// <param name="samplingRate">The sampling rate.</param>
        /// <param name="monitoringPriority">The monitoring priority.</param>
        public VirtualMemoryMonitor(double messageLimit, double samplingRate, MonitoringPriority monitoringPriority)
            : base(messageLimit, samplingRate, monitoringPriority)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="VirtualMemoryMonitor"/> class.
        /// </summary>
        /// <param name="messageLimit">The message limit. If the message limit get exceed the monitor 
        /// automatically throws a LimitExceedanceEvent.</param>
        /// <param name="samplingRate">The sampling rate.</param>
        /// <param name="monitoringPriority">The monitoring priority.</param>
        /// <param name="startMonitoring">if set to <c>true</c> the monitor will start automatically
        /// otherwise, it must be started by method Start().</param>
        public VirtualMemoryMonitor(double messageLimit, double samplingRate, MonitoringPriority monitoringPriority,
                                    bool startMonitoring)
            : base(messageLimit, samplingRate, monitoringPriority, startMonitoring)
        {
        }

        /// <summary>
        /// Gets the virtual memory usage.
        /// </summary>
        /// <value>The virtual memory usage.</value>
        public double VirtualMemoryUsage
        {
            get
            {
                double memoryUsage = 0;
                ManagementObjectSearcher searcher =
                    new ManagementObjectSearcher("select FreeVirtualMemory from Win32_OperatingSystem");

                foreach (ManagementObject obj in searcher.Get())
                {
                    memoryUsage += (Convert.ToDouble(obj["FreeVirtualMemory"], CultureInfo.CurrentCulture));
                }

                return memoryUsage / 1048576;
            }
        }

        /// <summary>
        /// Handles the Tick event of the samplingTimer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void SamplingTimer_Tick(object sender, EventArgs e)
        {
            double usage = this.VirtualMemoryUsage;

            if (usage >= base.MessageLimit)
            {
                this.VirtualMemoryUsageEvent(usage);
            }
        }
    }
}